package com.murong.ai.chat.infrastructure.utils;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;

public class MrSpringContextHolder implements ApplicationContextAware, DisposableBean {
    private static ApplicationContext applicationContext = null;
    private static Cache<String, String> propertyCache = CacheBuilder.newBuilder().maximumSize(200L).build();
    private static Cache<String, String> nullPropertyCache = CacheBuilder.newBuilder().maximumSize(100L).build();

    public MrSpringContextHolder() {
    }

    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    public static void registerBean(String name, Object bean) {
        DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory)((ConfigurableApplicationContext)applicationContext).getBeanFactory();
        defaultListableBeanFactory.registerSingleton(name, bean);
    }

    public static void removeBean(String name) {
        DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory)((ConfigurableApplicationContext)applicationContext).getBeanFactory();
        defaultListableBeanFactory.destroySingleton(name);
    }

    public void setApplicationContext(ApplicationContext appContext) {
        applicationContext = appContext;
    }

    public static <T> T getBean(Class<T> requiredType) {
        return applicationContext.getBean(requiredType);
    }

    public static <T> T getBean(String name, Class<T> requiredType) {
        return applicationContext.getBean(name, requiredType);
    }

    public static void clearHolder() {
        applicationContext = null;
    }

    public static String getProperty(String name) {
        if (getApplicationContext() == null) {
            return null;
        } else if (getApplicationContext().getEnvironment() == null) {
            return null;
        } else {
            String value = (String)nullPropertyCache.getIfPresent(name);
            if (value != null) {
                return null;
            } else {
                value = (String)propertyCache.getIfPresent(name);
                if (value != null) {
                    return value;
                } else {
                    value = getApplicationContext().getEnvironment().getProperty(name);
                    if (value != null) {
                        propertyCache.put(name, value);
                    } else {
                        nullPropertyCache.put(name, "");
                    }

                    return value;
                }
            }
        }
    }

    public static String getProperty(String name, String defaultValue) {
        if (getApplicationContext() == null) {
            return null;
        } else if (getApplicationContext().getEnvironment() == null) {
            return null;
        } else {
            String value = (String)propertyCache.getIfPresent(name);
            if (value != null) {
                return value;
            } else {
                value = getApplicationContext().getEnvironment().getProperty(name, defaultValue);
                if (value != null) {
                    propertyCache.put(name, value);
                }

                return value;
            }
        }
    }

    public static String getApplicationName() {
        return getProperty("spring.application.name");
    }

    public void destroy() throws Exception {
        clearHolder();
    }
}
